package com.nut.interceptor;

import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.io.Serializable;
import java.util.*;

/**
 * jwt加解密工具类
 */
@Component
@Slf4j
public class JwtTokenUtil implements Serializable {

    private static final long serialVersionUID = -3301605591108950415L;

    // Web端
    private static final String KEY_USERID = "userId";
    private static final String KEY_USERNAME = "username";
    private static final String KEY_NICKNAME = "nickname";
    private static final String KEY_DEPT_CODE = "deptCode";
    private static final String KEY_ROLES = "roles";

    // Wx端
    private static final String KEY_OPENID = "openid";
    private static final String KEY_MEMBER_ID = "memberId";
    private static final String KEY_SESSION_KEY = "sessionkey";

    private String secret = "56gu25@41qweH]>0$#";

    //时长2小时
    private Long expiration = 14400L;

    public UserJwt getUserJwtFormToken(String token) {
        try {
            final Claims claims = getClaimsFromToken(token);
            if (claims != null) {
                UserJwt userJwt = new UserJwt();
                if (claims.get(KEY_USERID) != null) {
                    userJwt.setUserId(Integer.valueOf(claims.get(KEY_USERID).toString()));
                }
                if (claims.get(KEY_USERNAME) != null) {
                    userJwt.setUsername(String.valueOf(claims.get(KEY_USERNAME)));
                }
                if (claims.get(KEY_NICKNAME) != null) {
                    userJwt.setNickname(String.valueOf(claims.get(KEY_NICKNAME).toString()));
                }
                if (claims.get(KEY_DEPT_CODE) != null) {
                    userJwt.setDeptCode(String.valueOf(claims.get(KEY_DEPT_CODE).toString()));
                }
                if (claims.get(KEY_ROLES) != null) {
                    List<Integer> roles = (List<Integer>) claims.get(KEY_ROLES);
                    userJwt.setRoleIds(roles);
                }
                return userJwt;
            }
        } catch (Exception e) {
            return null;
        }
        return null;
    }

    public UserJwtWx getUserJwtWxFormToken(String token) {
        try {
            final Claims claims = getClaimsFromToken(token);
            if (claims != null) {
                UserJwtWx userJwt = new UserJwtWx();
                if (claims.get(KEY_OPENID) != null) {
                    userJwt.setOpenid(String.valueOf(claims.get(KEY_OPENID)));
                }
                if (claims.get(KEY_SESSION_KEY) != null) {
                    userJwt.setSessionkey(String.valueOf(claims.get(KEY_SESSION_KEY)));
                }
                if (claims.get(KEY_MEMBER_ID) != null) {
                    userJwt.setMemberId(Long.valueOf(claims.get(KEY_MEMBER_ID).toString()));
                }
                return userJwt;
            }
        } catch (Exception e) {
            return null;
        }
        return null;
    }

    public Claims getClaimsFromToken(String token) {
        Claims claims;
        try {
            claims = Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token)
                    .getBody();
        } catch (Exception e) {
            log.error("jwt_error," + e);
            claims = null;
        }
        return claims;
    }

    public String generateToken(UserJwt userJwt) {
        Map<String, Object> claims = new HashMap<>();
        claims.put(KEY_USERID, userJwt.getUserId());
        claims.put(KEY_USERNAME, userJwt.getUsername());
        claims.put(KEY_NICKNAME, userJwt.getNickname());
        claims.put(KEY_DEPT_CODE, userJwt.getDeptCode());
        claims.put(KEY_ROLES, userJwt.getRoleIds());
        return generateToken(claims);
    }

    public String generateToken(UserJwtWx userJwt) {
        Map<String, Object> claims = new HashMap<>();
        claims.put(KEY_OPENID, userJwt.getOpenid());
        claims.put(KEY_SESSION_KEY, userJwt.getSessionkey());
        claims.put(KEY_MEMBER_ID, userJwt.getMemberId());
        return generateToken(claims);
    }

    private String generateToken(Map<String, Object> claims) {
        Date date = new Date(System.currentTimeMillis() + expiration * 1000);
        return Jwts.builder()
                .setClaims(claims)
                .setExpiration(date)
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();
    }

    public String refreshToken(Claims claims) {
        try {
            Date expiration = claims.getExpiration();
            //如果当前时间超过持有时长的一半，则需要刷新token
            if (System.currentTimeMillis() + (this.expiration / 2) > expiration.getTime()) {
                return generateToken(claims);
            }
        } catch (Exception e) {
            return null;
        }
        return null;
    }

    public static void main(String[] args) {

//        System.out.println(UUID.randomUUID().toString().replace("-", ""));
//        System.out.println(UUID.randomUUID().toString().replace("-", ""));
//        System.out.println(UUID.randomUUID().toString().replace("-", ""));


        UserJwt userJwt = new UserJwt();
        userJwt.setUsername("openId");
        userJwt.setUserId(1);

        JwtTokenUtil jwtTokenUtil = new JwtTokenUtil();

        String token = jwtTokenUtil.generateToken(userJwt);
        UserJwt userJwt1 = jwtTokenUtil.getUserJwtFormToken(token);
        System.out.println(userJwt1.getUsername());


        UserJwtWx userJwtWx = new UserJwtWx();
        userJwtWx.setOpenid("dddd");
        userJwtWx.setMemberId(42342L);
        String token1 = jwtTokenUtil.generateToken(userJwtWx);

        UserJwtWx userJwtWx2 = jwtTokenUtil.getUserJwtWxFormToken(token1);

        System.out.println(userJwtWx2.getOpenid());
        System.out.println(userJwtWx2.getMemberId());

    }
}

